/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

//import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Timer;
//import org.soft.database.XML;

/**
 *
 * @author Doc
 * Class Worker Administration
 */
public class Mitarbeiterverwaltung {

	
	private static Timer timerAutoBackup  = new Timer();
	private Systemproperties	systemproperties;
	
    // private ArrayList<Mitarbeiter> mListe;
    private Hashtable<Integer,Mitarbeiter> MitarbeiterListeMain = new Hashtable<Integer,Mitarbeiter>();
    private Hashtable<Integer,Administratoren> hashAdmins = new Hashtable<Integer,Administratoren>();
    private Hashtable<Integer,Systemproperties> hashSystemProperties = new Hashtable<Integer,Systemproperties>();

    
    /**database*/
    //   private XML database = new XML("root");
    //	 later on
    	

    /**
     * Constructor Class Mitarbeiterverwaltung
     */
    public Mitarbeiterverwaltung() throws Exception {
    	
    	// generate Folder Database
    	File file = new File("Database");
    	if(!file.exists()){
    		file.mkdirs();
    	}
    	
    	// generate Folder Backups
    	File fileBackups = new File("Backups");
    	if(!fileBackups.exists()){
    		fileBackups.mkdirs();
    	}
    	
    	// generate Folder Backups
    	File fileBackupsLongVersion = new File("Backups/LongVersion");
    	if(!fileBackupsLongVersion.exists()){
    		fileBackupsLongVersion.mkdirs();
    	}
    	
    	// generate Folder Backups
    	File fileBackupsHumanVersion = new File("Backups/HumanVersion");
    	if(!fileBackupsHumanVersion.exists()){
    		fileBackupsHumanVersion.mkdirs();
    	}
    	
    	// generate workerFile Worker.obj
    	File workerFile = new File("Database/Worker.obj");
    	if(!workerFile.exists()){
    		this.mitarbeiterAuslesen();
    	}
    	
    	// generate AdminFile Admin.obj
    	File adminFile = new File("Database/Admin.obj");
    	if(!adminFile.exists()){
    		this.adminsAuslesen();
    	}
    	
    	// generate systemPropertiesFile systemProperties.obj
    	File systemPropertiesFile = new File("Database/systemProperties.obj");
    	if(!systemPropertiesFile.exists()){
    		this.systemPropertiesAuslesen();
    	}
    	
    	//read in for Objects
    	mitarbeiterEinlesen();
    	adminsEinlesen();
    	systemPropertiesEinlesen();
    	
    	
    	
    	//if none SystemTime is Exists use default Values else use the User Generated one
    	if(listSystemPropertiesIteriert()==null){
    		//set first SystemTime
    		long systemTime = Timeparse.getSystemTimeParsed();
    		// ID 1, SysTime from start, Backup every 4hours, ID from root, maxMorningTime 9:30 AM
    		this.systemPropertiesAnlegen(1, systemTime, 14400000, 88, 570);
    		setSystemproperties(sucheSystemPropertiesHM(1));
    	}
    	else{
    		Integer[] sysList = listSystemPropertiesIteriert();
    		int counter = sysList.length;
    		setSystemproperties(sucheSystemPropertiesHM(counter));
    	}
    	//check
    	System.out.println("set SystemProperties to ID: " + this.systemproperties.getId());
    	
    	// SU einrichten
    	adminAnlegen("root", "root", 88, "root", 1);
    	
    	//If some User havent been logtOut last Workday
    	Integer[] worker = this.onlineCheck();
    	if(worker != null){
    		for(int i = worker.length; i >= 1 ;i--){
    			this.sucheMitarbeiterHM(worker[i-1]).setLogOut();
    			System.out.println("Es wurde der Mitarbeiter: "+ this.sucheMitarbeiterHM(worker[i-1]).getID() +" beim restart zwangs ausgelogt");
    			System.out.println("Bitte Zeiten pruefen!");
    		}
    	}
    	
    	//Auto Backup every 4 hours get the Value from Users settings in SystemProperties
    	long backupTime = this.systemproperties.getBackupTime();
    	timerAutoBackup.schedule(new TimerBackup(this), 0, backupTime);
    	//check
    	System.out.println("backupTime: " + backupTime);
    	//check
    	long maxMorningTime = this.systemproperties.getMaxMorningStandartTime();
    	System.out.println("maxMorningTime: " + maxMorningTime);
    	
    	//TODO check the SysProperties Feiertage array and set them to all Users month Array
    	Timecalculator.setFreedaysToWorkers(this);
    	
    	
    }

    /**
     * add Worker with Vorname, Name, Alter, PW, ID
     */
    public void mitarbeiterAnlegen(String vorname, String name, Integer id, int alter, String pw, long mWorkTime, long Overtime, int holidays){

    	Mitarbeiter mitarbeiter = new Mitarbeiter(vorname, name, alter, pw, id, holidays);
    	MitarbeiterListeMain.put(id,mitarbeiter);
    	
    	int m = 0;
    	int d = 0;
    	// Wert 4 für monthlyWorkTime
    	int v = 4;
    	mitarbeiter.setMonthlyWorkTime(m, d, v, mWorkTime);
    	
    	// Set Overtime (Gelitzeit)
    	mitarbeiter.setOvertime(Overtime);
    	
    	
    	//TODO Hier was da steht ^^
    	// zukünftig m d und v from get instanz dann kann admin spezifisch für moanthe anlegen HIWIS
    	// methode in Mitarbeiter muss geändert werden
//    	int m = Calendar.getInstance().get(Calendar.MONTH)+1; // Jan = 0
//		int d = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
//		int y = Calendar.getInstance().get(Calendar.YEAR);
//		// Wert 3 für monthlyWorkTime
//		int v = 3;
//		System.out.println(m);
//		System.out.println(d);
//		System.out.println(y);
//    	mitarbeiter.setMonthlyWorkTime(m, d, v, time);
//    	//test
//    	System.out.println(mitarbeiter.getMonthlyWorkTime());
                 
    }
    
    /**
     * add Admin with Vorname, Name, PW, ID, rights
     */
    public void adminAnlegen(String vorname, String name, Integer id, String pw, int rights){

    	Administratoren administratoren = new Administratoren(vorname, name, pw, id, rights);
    	hashAdmins.put(id,administratoren);
    	administratoren.setRights(rights);
                 
    }
    
    /**
     * add SystemProperties with Integer id, long systemTime,long backUpTime,Integer lastEditedUser
     */
    public void systemPropertiesAnlegen(Integer id, long systemTime,long backUpTime,Integer lastEditedUser, long maxMorningStandartTime){

    	Systemproperties systemproperties = new Systemproperties(id, systemTime, backUpTime, lastEditedUser, maxMorningStandartTime);
    	hashSystemProperties.put(id,systemproperties);
                 
    }

    /**
     * liest Mitarbeiter Objekte in hashListe ein
     */
    @SuppressWarnings("unchecked")
	private void mitarbeiterEinlesen() throws Exception {
    	MitarbeiterListeMain = null;
    	//hashListe = (hashListe()) ois.readObject();
		try {
			FileInputStream fis = new FileInputStream("Database/Worker.obj");
			ObjectInputStream ois = new ObjectInputStream(fis);
			MitarbeiterListeMain = (Hashtable)ois.readObject();
			ois.close();
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
    }
    
    /**
     * Speichert Mitarbeiter Objekte aus hashListe in Datei
     */
    public void mitarbeiterAuslesen() throws Exception {
    	
    	FileOutputStream fileOut;
		try {
			fileOut = new FileOutputStream("Database/Worker.obj");
			ObjectOutputStream oos = new ObjectOutputStream(fileOut);
			oos.writeObject(MitarbeiterListeMain);
			oos.close();
			fileOut.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}   	
    }
    
    /**
     * liest Mitarbeiter Objekte in hashListe ein
     */
    @SuppressWarnings("unchecked")
	private void adminsEinlesen() throws Exception {
    	hashAdmins = null;
    	//hashListe = (hashListe()) ois.readObject();
		try {
			FileInputStream fis = new FileInputStream("Database/Admin.obj");
			ObjectInputStream ois = new ObjectInputStream(fis);
			hashAdmins = (Hashtable)ois.readObject();
			ois.close();
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
    }
    
    /**
     * Speichert Admin Objekte aus hashListe in Datei
     */
    public void adminsAuslesen() throws Exception {
    	
    	FileOutputStream fileOut;
		try {
			fileOut = new FileOutputStream("Database/Admin.obj");
//			 umwandeln in lesbares Format GEHT NICHT
//			XMLEncoder e = new XMLEncoder(fileOut);
			ObjectOutputStream oos = new ObjectOutputStream(fileOut);
			oos.writeObject(hashAdmins);
			oos.close();
			fileOut.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}   	
    }
    
    
    /**
     * saves SystemProperties Objects in a hashtable 
     */
    @SuppressWarnings("unchecked")
	private void systemPropertiesEinlesen() throws Exception {
    	hashSystemProperties = null;
    	//hashListe = (hashListe()) ois.readObject();
		try {
			FileInputStream fis = new FileInputStream("Database/systemProperties.obj");
			ObjectInputStream ois = new ObjectInputStream(fis);
			hashSystemProperties = (Hashtable)ois.readObject();
			ois.close();
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
    }
    
    /**
     * saves SystemProperties Objects out of hashtable in a file
     */
    public void systemPropertiesAuslesen() throws Exception {
    	
    	FileOutputStream fileOut;
		try {
			fileOut = new FileOutputStream("Database/systemProperties.obj");
			ObjectOutputStream oos = new ObjectOutputStream(fileOut);
			oos.writeObject(hashSystemProperties);
			oos.close();
			fileOut.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}   	
    }
    
    
    /**
     * generates the Name for the txt File
     * returns a Value of Time in String Version
     */
    public String getBackupName(){
    	
    	// get Date and Time for the Name of the File
    	int[] date = Timeparse.getDate();
    	int day = date[0];
    	int month = date[1];
    	int year = date[2];
    	
    	int time[] = Timeparse.getTime();
    	int hour = time[0];
    	int min = time[1];
    	int sec = time[2];
    	
    	String titel = String.valueOf(year) + " " + String.valueOf(month) +
    			" " + String.valueOf(day) + " " + String.valueOf(hour) +
    			"-" + String.valueOf(min) + "-" + String.valueOf(sec) ;
    	
    	
    	return titel;
    }
    
    /**
     * search Worker by id
     * @param id
     * @return
     */
    public Mitarbeiter sucheMitarbeiterHM(Integer id){       
    if(MitarbeiterListeMain.get(id) == null){
        System.out.println ("Mitarbeiter mit der ID: "+id+" konnte nicht gefunden werden");
        return null;
       }
       return MitarbeiterListeMain.get(id);
    }
    
    public Administratoren sucheAdministratorenHM(Integer id){       
    if(hashAdmins.get(id) == null){
        System.out.println ("Administrator mit der ID: "+id+" konnte nicht gefunden werden");
        return null;
       }
       return hashAdmins.get(id);
    } 
    
    public Systemproperties sucheSystemPropertiesHM(Integer id){       
        if(hashSystemProperties.get(id) == null){
            System.out.println ("SystemProperties mit der ID: " + id + " konnte nicht gefunden werden");
            return null;
           }
           return hashSystemProperties.get(id);
        } 
    
    
    /**
     * removes Worker by id
     * @param id
     */
    public void removeMitarbeiter(Integer id){
        MitarbeiterListeMain.remove(id);
    }
    
    public void removeAdministrator(Integer id){
        hashAdmins.remove(id);
    }
  
    @Deprecated  
    /**
     * lists all Workers
     */
    public void listWorkers(){
    	
    	for(int key : MitarbeiterListeMain.keySet())
        {
    		System.out.println("\n");
    		System.out.print(MitarbeiterListeMain.get(key).getVorname());
    		System.out.println(" "+MitarbeiterListeMain.get(key).getName());
    		System.out.println("Alter: "+MitarbeiterListeMain.get(key).getAlter());
    		System.out.println("PersonalNr.: "+MitarbeiterListeMain.get(key).getID());
    		System.out.println("Passwort: "+MitarbeiterListeMain.get(key).getPw());
    	}
    	System.out.println("Es gibt "+MitarbeiterListeMain.size()+" Eintraege");
    }
    
    @Deprecated  
    /**
     * lists all Admins
     */
    public void listAdmins(){
    	
    	for(int key : hashAdmins.keySet())
        {
    		System.out.println("\n");
    		System.out.print(hashAdmins.get(key).getVorname());
    		System.out.println(" "+hashAdmins.get(key).getName());
    		System.out.println("PersonalNr.: "+hashAdmins.get(key).getID());
    		System.out.println("Passwort: "+hashAdmins.get(key).getPw());
    	}
    	System.out.println("Es gibt "+hashAdmins.size()+" Eintraege");
    }
   
    /**
     * lists all workers
     * @return Integer[] with id's
     */
    public Integer[] listWorkersIteriert(){
    	ArrayList<Integer> w = new ArrayList<Integer>();
    	
    	for (Enumeration<Mitarbeiter> e = MitarbeiterListeMain.elements();e.hasMoreElements();){
    		Mitarbeiter worker = e.nextElement();
    		w.add(worker.getID());
    	}
    	
    	if(w.isEmpty()){
    		 return null;
        }
    	
    	w.trimToSize();

    	Integer[] s = new Integer[w.size()];
    	for(int i=0;i<w.size();i++){
    		s[i]=w.get(i);
    	}
    	return s;
    }  
    
    /**
     * lists all Admins
     * @return Integer[] with id's
     */
    public Integer[] listAdministratorenIteriert(){
    	ArrayList<Integer> w = new ArrayList<Integer>();
    	
    	for (Enumeration<Administratoren> e = hashAdmins.elements();e.hasMoreElements();){
    		Administratoren admins = e.nextElement();
    		w.add(admins.getID());
    	}
    	
    	if(w.isEmpty()){
    		 return null;
        }
    	
    	w.trimToSize();

    	Integer[] s = new Integer[w.size()];
    	for(int i=0;i<w.size();i++){
    		s[i]=w.get(i);
    	}
    	return s;
    } 
    
    /**
     * lists all System Properties
     * @return Integer[] with id's
     */
    public Integer[] listSystemPropertiesIteriert(){
    	ArrayList<Integer> w = new ArrayList<Integer>();
    	
    	for (Enumeration<Systemproperties> e = hashSystemProperties.elements();e.hasMoreElements();){
    		Systemproperties systems = e.nextElement();
    		w.add(systems.getId());
    	}
    	
    	if(w.isEmpty()){
    		 return null;
        }
    	
    	w.trimToSize();

    	Integer[] s = new Integer[w.size()];
    	for(int i=0;i<w.size();i++){
    		s[i]=w.get(i);
    	}
    	return s;
    } 
    
    /**
     * check Workers id with pw and returns boolean
     * @param id
     * @return
     */
    public boolean pwCheck(Integer id, String pw){
    	
    	if (sucheMitarbeiterHM(id) != null){
    		System.out.println("Bitte Passwort eingeben: ");
        	if (pw.equals(sucheMitarbeiterHM(id).getPw())){
        		return true;
        	}
        	System.out.println("Passwort falsch");
        	System.out.println("Man beachte die Gross-kleinschreibung!");
        	return false;
    	}
    	return false;
    }
    
    public boolean pwCheckAdmin(Integer id, String pw){
    	
    	if (sucheAdministratorenHM(id) != null){
    		System.out.println("Bitte Passwort eingeben: ");
        	if (pw.equals(sucheAdministratorenHM(id).getPw())){
        		return true;
        	}
        	System.out.println("Passwort falsch");
        	System.out.println("Man beachte die Gross-kleinschreibung!");
        	return false;
    	}
    	return false;
    }
    
    /**
     * checks who is logtIn
     * @return Integer[] with all id's are logtIn
     */
    public Integer[] onlineCheck(){
    	ArrayList<Integer> w = new ArrayList<Integer>();

    	for (Enumeration<Mitarbeiter> e = MitarbeiterListeMain.elements();e.hasMoreElements();){
    		Mitarbeiter worker = e.nextElement();
    		if(worker.getLogtIn()== true){
    			w.add(worker.getID());
    			//check
    			//System.out.println("onlineCheck add: " + worker.getID());
    		}
    	}
    	
    	if(w.isEmpty()){
    		 //check
    		 //System.out.println("onlineCheck return null w is empty");
    		 return null;
        }
    	
    	w.trimToSize();

    	Integer[] s = new Integer[w.size()];
    	for(int i=0;i<w.size();i++){
    		s[i]=w.get(i);
    	}
    	//check
    	//System.out.println("onlineCheck return Integer[] s" + s[0]);
    	return s;
    }

	public Systemproperties getSystemproperties() {
		return systemproperties;
	}

	public void setSystemproperties(Systemproperties systemproperties) {
		this.systemproperties = systemproperties;
	}
    

} // end Class Mitarbeiterverwaltung
